﻿// --------------------------------------------------------------------------------------------------------------------- 
// <copyright file="SieveOfEratosthenes.cs" company="Microsoft">
//   Copyright (c) Microsoft Corporation.  All rights reserved. THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// </copyright>
// <summary>
//   Defines the SieveOfEratosthenes type.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------
namespace EulerProblemsCSharp
{
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// Generates prime numbers using the Sieve of Eratosthenes.
    /// </summary>
    public class SieveOfEratosthenes
    {
        /// <summary>
        /// Generates a sequence of primes.
        /// </summary>
        /// <param name="max">
        /// The max value to return. Primes less than or equal to this value will be returned.
        /// </param>
        /// <returns>
        /// An sequence of primses as an IEnumerable of long.
        /// </returns>
        public IEnumerable<long> GetPrimes(int max)
        {
            var nonprimes = new bool[max + 1];

            for (long i = 2; i <= max; i++)
            {
                if (nonprimes[i] == false)
                {
                    for (var j = i * i; j <= max; j += i)
                    {
                        nonprimes[j] = true;
                    }

                    yield return i;
                }
            }
        }

        /// <summary>
        /// Generates a sequence of primes.
        /// </summary>
        /// <param name="max">
        /// The max value to return. Primes less than or equal to this value will be returned.
        /// </param>
        /// <returns>
        /// An sequence of primses as an IEnumerable of long.
        /// </returns>
        public IEnumerable<long> GetPrimes2(int max)
        {
            var nonprimes = new bool[max + 1];

            return Enumerable.Range(2, max - 1)                
                .Where(i => !nonprimes[i])                
                .Select(
                    i =>
                    {
                        for (long j = i; j <= max; j += i)
                        {                            
                            nonprimes[j] = true;
                        }

                        return (long)i;
                    });
        }
    }
}